//
//  LGControllerManager.m
//  ALS-02
//
//  Created by guomianxiang on 16/11/9.
//  Copyright © 2016年 guomianxiang. All rights reserved.
//

#import "LGControllerManager.h"
#import "ALSConstNSString.h"
#import "NSString+LG.h"
#import "ALSHeader.h"
@interface LGControllerManager ()

@property (strong, nonatomic) NSMutableArray<LGController *> *controllersInfoMArr;
@property (strong, nonatomic, nullable) NSMutableArray <LGDoor *>* doorsInfoMArr;

// 外部接口
@property (strong, readwrite, nonatomic, nullable) NSArray <LGController *>* controllers;
@property (strong, readwrite, nonatomic, nullable) NSArray <LGDoor *>* doors;
// 外部接口 - 已排序doors
@property (strong, readwrite, nonatomic, nullable) NSArray <NSArray <LGDoor *>*>*letterOrderDoors;
@property (strong, readwrite, nonatomic, nullable) NSArray <LGDoor *>*usefulFrequencyOrderDoors;



@property (strong, nonatomic) NSString *controllersInfoPath;

@property (strong, nonatomic) NSMutableArray <NSString *>*usedDoors;


@end



@implementation LGControllerManager

static id _instance;

+ (instancetype)allocWithZone:(struct _NSZone *)zone {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [super allocWithZone:zone];
    });
    return _instance;
}

+ (instancetype)shareControllerManager {
    if (_instance) return _instance;
    return [[self alloc]init];
}

- (instancetype)init {
    if (self == [super init]) {
        [self compatibleWithPreviousVersions];
        [self controllersInfoMArr];
        [self setupDoorsInfoMArr];
        [self setupDoors];
        [self setupControllers];
        [self setupLetterOrderDoors];
        [self setupUsefulFrequencyOrderDoors];
    }
    return self;
}
// 迁移数据 兼容老版本
- (void)compatibleWithPreviousVersions {
    
    NSMutableArray *oldControllersMarr;
    
    NSString *cachesPath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];
    NSString *filePath = [cachesPath stringByAppendingString:@"controllersMArr.data"];
    oldControllersMarr = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
    
    if (oldControllersMarr.count > 0) {
        // 删除数据
        NSError *error;
        [[NSFileManager defaultManager]removeItemAtPath:filePath error:&error];
        if (error) {
            NSLog(@"%@",error.localizedDescription);
            NSLog(@"%lu",error.code);
        }else {
            NSLog(@"删除老版本数据成功");
        }
        
        // 迁移老版本数据
        NSLog(@"迁移老版本数据");
        for (LGController *item in oldControllersMarr) {
            NSMutableArray *doorMarr = [NSMutableArray array];
            for (int i=0; i<item.doors.count; i++) {
                LGDoor *door = [[LGDoor alloc]init];
                if ([item.doors[i] isKindOfClass:[NSString class]]) {
                    door.doorName = (NSString *)item.doors[i];
                }
                door.valid = YES;
                door.show = YES;
                [doorMarr addObject:door];
            }
            item.doors = [NSArray arrayWithArray:doorMarr];
        }
        _controllersInfoMArr = oldControllersMarr;
        oldControllersMarr = nil;
    }

}
// 增加
- (void)addItem:(LGController *)item reply:(void (^)(BOOL, NSError *))reply {
    NSError *error;
    
    if (![self isExistsItem:item]) {
        [self.controllersInfoMArr addObject:item];

        if ([self save]) {
            [[NSNotificationCenter defaultCenter]postNotificationName:CMAddedItemNotification object:nil];
            reply(YES,nil);
        }else {
            [self.controllersInfoMArr removeLastObject];
            error = [NSError errorWithDomain:NSStringFromClass([LGControllerManager class]) code:LGControllerManagerErrorSaveFailed userInfo:@{NSLocalizedDescriptionKey : @"保存失败"}];
            reply(NO,error);
        }
    }else {
        error = [NSError errorWithDomain:NSStringFromClass([LGControllerManager class]) code:LGControllerManagerErrorExisted userInfo:@{NSLocalizedDescriptionKey : @"S/N码已存在"}];
        reply(NO,error);
    }
}
// 删除
- (void)removeItem:(LGController *)item reply:(void(^)(BOOL success, NSError *error))reply {
//#warning 删除数据 removeObject 是如何工作的？
    NSError *error;
    NSUInteger i;
    if ([self isExistsItem:item]) {
        i = [self searchItem:item];

        LGController *oldItem = self.controllersInfoMArr[i];
        [self.controllersInfoMArr removeObjectAtIndex:i];

        if ([self save]) {
            [[NSNotificationCenter defaultCenter]postNotificationName:CMDeleteItemNotification object:nil];

            reply(YES,nil);
        }else {
            [self.controllersInfoMArr insertObject:oldItem atIndex:i];
            error = [NSError errorWithDomain:NSStringFromClass([LGControllerManager class]) code:LGControllerManagerErrorSaveFailed userInfo:@{NSLocalizedDescriptionKey : @"保存失败"}];
            reply(NO,error);
        }
    }else {
        error = [NSError errorWithDomain:NSStringFromClass([LGControllerManager class]) code:LGControllerManagerErrorNotExist userInfo:@{NSLocalizedDescriptionKey : @"S/N码不存在"}];
        reply(NO,error);
    }
}
- (void)removeAllItem {
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        [self.controllersInfoMArr removeAllObjects];
        [self save];
    });
}
// 改
- (void)editItem:(LGController *)item reply:(void(^)(BOOL success, NSError *error))reply {
    NSUInteger index = [self searchItem:item];
    LGController *oldItem = self.controllersInfoMArr[index];
    self.controllersInfoMArr[index] = item;
    
    NSError *error;
    if ([self save]) {
        
        [[NSNotificationCenter defaultCenter]postNotificationName:CMEditItemNotification object:nil];

        reply(YES,nil);

    }else {
        self.controllersInfoMArr[index] = oldItem;

        error = [NSError errorWithDomain:NSStringFromClass([LGControllerManager class]) code:LGControllerManagerErrorSaveFailed userInfo:@{NSLocalizedDescriptionKey : @"保存失败"}];
        reply(NO,error);
    }
}
- (void)setFavoriteWith:(LGDoor *)door {
    LGDoor *item = _controllersInfoMArr[door.controllerIndex].doors[door.doorIndex];
    item.favorite = !item.favorite;

    [NSKeyedArchiver archiveRootObject:self.controllersInfoMArr toFile:self.controllersInfoPath];
    [self setupUsefulFrequencyOrderDoors];
}
// 查
- (NSUInteger)searchItem:(LGController *)item {
    NSUInteger i;
    for (i = 0; i<self.controllersInfoMArr.count; i++) {
        if ([self.controllersInfoMArr[i].sn isEqualToString:item.sn]) {
            break;
        }
    }
    return i;
}
- (BOOL)isExistsItemWithSN:(NSString *)SN {
    for (LGController *one in self.controllersInfoMArr) {
        if ([one.sn isEqualToString:SN]) {
            return YES;
        }
    }
    return NO;
}
- (BOOL)isExistsItem:(LGController *)item {
    return [self isExistsItemWithSN:item.sn];
}
- (void)searchDoorWith:(NSString *)text reply:(void (^)(NSArray <LGDoor *>* _Nullable))reply {
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSString *lowercaseStr = [text stringTransformPinYin];
        NSMutableArray *originalResultArr = [NSMutableArray array];
        NSMutableArray *pinYinResultArr = [NSMutableArray array];
        for (LGDoor *item in _doors) {
            NSRange range = [item.doorName rangeOfString:text];
            if (range.length == 0) {
                if ([item.pinyin containsString:lowercaseStr]) {
                    [pinYinResultArr addObject:item];
                }
            }else {
                LGDoor *door = [item copy];
                NSMutableAttributedString *attributed = [[NSMutableAttributedString alloc]initWithString:door.doorName];
                [attributed addAttribute:NSForegroundColorAttributeName value:kALSHightBlueColor range:range];
                door.attributedName = attributed;

                [originalResultArr addObject:door];
            }

        }
        
        if (originalResultArr.count == 0) {
            if (pinYinResultArr.count > 0) {
                originalResultArr = pinYinResultArr;
            }else {
                originalResultArr = nil;
            }
        }
        
        dispatch_async(dispatch_get_main_queue(), ^{
            reply(originalResultArr);
        });
        
    });
}
- (void)searchDoorWithAndRecommend:(NSString *)text reply:(void (^)(NSArray<LGDoor *> * _Nullable, NSArray<LGDoor *> * _Nullable))reply {
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSString *lowercaseStr = [text stringTransformPinYin];
        NSMutableArray *resultArr = [NSMutableArray array];
        NSMutableArray *recommendArr = [NSMutableArray array];
        
        for (LGDoor *item in _doors) {
            NSRange range = [item.doorName rangeOfString:text];
            if (range.length == 0) {
                if ([item.pinyin containsString:lowercaseStr]) {
                    [recommendArr addObject:item];
                }
            }else {
                LGDoor *door = [item copy];
                NSMutableAttributedString *attributed = [[NSMutableAttributedString alloc]initWithString:door.doorName];
                [attributed addAttribute:NSForegroundColorAttributeName value:kALSHightBlueColor range:range];
                door.attributedName = attributed;
                
                [resultArr addObject:door];
            }
            
        }
        
        if (resultArr.count == 0) resultArr = nil;
        if (recommendArr.count == 0) recommendArr = nil;
        
        
        dispatch_async(dispatch_get_main_queue(), ^{
            reply(resultArr,recommendArr);
        });
        
    });
}
// 保存
- (BOOL)save {
    BOOL result = [NSKeyedArchiver archiveRootObject:self.controllersInfoMArr toFile:self.controllersInfoPath];
    if (!result) {
        return result;
    }
    
    
    [self setupDoorsInfoMArr];
    [self setupDoors];
    [self setupControllers];
    [self setupUsefulFrequencyOrderDoors];
    [self setupLetterOrderDoors];
    
    [[NSNotificationCenter defaultCenter]postNotificationName:CMItemChangedNotification object:nil];

    if (self.controllersInfoMArr.count == 0) {
        [[NSNotificationCenter defaultCenter]postNotificationName:CMDeleteAllItemNotification object:nil];
    }
    return result;
}
// 开门
- (void)openDoor:(LGDoor *)door reply:(void (^)(BOOL, NSError * _Nullable))reply {
    
    
    __weak typeof(self)weakSelf = self;
    
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        
        NSInteger port = [door.port integerValue];
        if (door.port.length == 0) port = 0;
        if (port == 0) port = 80;
        
        NSString *cPassWord = NSUDStrALSCommunicationPassWord;
        
        int cp = [cPassWord intValue];
        
        NSString *urlStr = [NSString stringWithFormat:@"http://%@:%ld/t,cgi?T%d,access_io,door,%lu,01",door.ip,(long)port,cp,(unsigned long)door.doorIndex];
        
        NSURL *url = [NSURL URLWithString:urlStr];
        
        NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url cachePolicy:1 timeoutInterval:2];
        
        
        [[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            
            dispatch_async(dispatch_get_main_queue(), ^{
                BOOL success = NO;
                NSError *replyError;
                
                if (data){
                    success = YES;
                    NSDictionary *dict = @{@"isSuccess" : @"YES",};
                    [MobClick event:UMEventOpenDoor attributes:dict];
                    [weakSelf performSelectorInBackground:@selector(recordTheFrequencyWithDoor:) withObject:door];
                    
                }
                
                if (error) {
                    
                    NSDictionary *dict = @{@"isSuccess" : @"NO",};
                    [MobClick event:UMEventOpenDoor attributes:dict];
                    
                    replyError = error;
                    //                NSLog(@"%@",error.localizedDescription);
                    //                error.code
                    //                NSLog(@"--%li",error.code);
                    //                未能连接到服务器。
                    //                ---1004
                    //                if (!error || ![error isEqual:@"ok"]) {
                    //                    NSLog(@"+++++++++++");
                    //                }
                }
                
                if (reply != nil) {
                    reply(success,replyError);
                }
                
            });
            
        }] resume];
    });
    
}
// 获取门状态
- (void)getDoorState:(LGDoor *)door reply:(void (^)(BOOL, NSError * _Nullable))reply {
    
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        
        //获取通讯密码
        NSString *cPassWord = NSUDStrALSCommunicationPassWord;
        //密码
        int cp = [cPassWord intValue];
        
        NSInteger port = [door.port integerValue];
        
        if (port == 0) {
            port = 80;
        }
        
        NSString *urlStr = [NSString stringWithFormat:@"http://%@:%ld/t.cgi?T%d,access_io,door_state,real,%li",door.ip,(long)port,cp,door.doorIndex];
        
        NSURL *url = [NSURL URLWithString:urlStr];
        
        NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url cachePolicy:1 timeoutInterval:2];
        
        [[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            
            NSString *dataStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
            
            BOOL open = NO;
            NSError *replyErrpr;
            
            if ([dataStr isEqualToString:@"1"]) {
                open = YES;
            } else if ([dataStr isEqualToString:@"0"]){
                open = NO;
            }
            
            if (error) {
                replyErrpr = error;
            }
            
            dispatch_async(dispatch_get_main_queue(), ^{
                if (reply) {
                    reply(open,replyErrpr);
                }
            });
            
        }] resume];
    });
}
// 设置门是否常用
- (void)setDoor:(LGDoor *)door Favorite:(NSInteger)favorite reply:(void (^)(NSIndexPath * _Nonnull))reply {
    
    __weak typeof(self) weakSelf = self;
    
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        LGDoor *item = weakSelf.controllersInfoMArr[door.controllerIndex].doors[door.doorIndex];
        [item setFavorite:favorite];
        
        [weakSelf setupDoors];
        [weakSelf setupLetterOrderDoors];
        [weakSelf setupUsefulFrequencyOrderDoors];
        
        for (NSUInteger i=0; i<weakSelf.usefulFrequencyOrderDoors.count; i++) {
            
            if ([item.doorName isEqualToString:weakSelf.usefulFrequencyOrderDoors[i].doorName]) {
                if (reply) {
                    dispatch_async(dispatch_get_main_queue(), ^{
                        NSIndexPath *changedIndexPath = [NSIndexPath indexPathForRow:i inSection:0];
                        
                        reply(changedIndexPath);
                        
                    });
                }
            }

        }
        [NSKeyedArchiver archiveRootObject:self.controllersInfoMArr toFile:self.controllersInfoPath];
        
    });
    
}
// 生成数据
- (void)setupControllers {
    _controllers = [[NSArray alloc]initWithArray:_controllersInfoMArr copyItems:YES];
}
- (void)setupDoorsInfoMArr {
    _doorsInfoMArr = [NSMutableArray array];
    
    for (int i=0; i<self.controllersInfoMArr.count; i++) {
        for (int j=0; j<self.controllersInfoMArr[i].doors.count; j++) {
            
            LGDoor *door = self.controllersInfoMArr[i].doors[j];
            
            if (!door.valid || !door.show) {
                continue;
            }
            
            door.controllerIndex = i;
            door.doorIndex = j;
            door.ip = self.controllersInfoMArr[i].ip;
            door.port = self.controllersInfoMArr[i].port;
            
            [_doorsInfoMArr addObject:door];
        }
    }
    
}
- (void)setupDoors {
    _doors = [[NSArray alloc]initWithArray:_doorsInfoMArr copyItems:YES];

}
- (void)setupLetterOrderDoors {
    
    NSMutableArray *tempMArr = [NSMutableArray array];
    
    NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"pinyin" ascending:YES];
    //这个数组保存的是排序好的对象
    NSArray *tempArray = [_doors sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
    
    
    char lastC = '1';
    NSMutableArray *data;
    NSMutableArray *other = [NSMutableArray array];
    for (int i=0; i<tempArray.count; i++) {
        
        LGDoor *door = tempArray[i];
        char letter = [door.pinyin characterAtIndex:0];
        
        if (!isalpha(letter)) {
            [other addObject:door];
        }
        else if (letter != lastC) {
            lastC = letter;
            if (data.count > 0) {
                [tempMArr addObject:data];
            }
            
            data = [NSMutableArray array];
            [data addObject:door];
        }
        else {
            [data addObject:door];
        }
    }
    
    if (data.count > 0) {
        [tempMArr addObject:data];
    }
    if (other.count > 0) {
        [tempMArr addObject:other];
    }
    
    _letterOrderDoors = [NSArray arrayWithArray:tempMArr];
}
- (void)setupUsefulFrequencyOrderDoors {
    NSMutableArray <LGDoor *>*tempMArr = [[NSMutableArray alloc]initWithArray:_doorsInfoMArr copyItems:YES];
    
    NSSortDescriptor *frequencyDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"frequency" ascending:YES];
    NSSortDescriptor *favoriteDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"favorite" ascending:YES];
    [tempMArr sortUsingDescriptors:[NSArray arrayWithObjects:favoriteDescriptor, frequencyDescriptor,nil]];
    
    tempMArr = (NSMutableArray *)[[tempMArr reverseObjectEnumerator]allObjects];
    
    
    _usefulFrequencyOrderDoors = [NSArray arrayWithArray:tempMArr];
//    NSLog(@"cm : %@",_usefulFrequencyOrderDoors);

}
// 记录开门频率
- (void)recordTheFrequencyWithDoor:(LGDoor *)door {
//    NSLog(@"%@",[NSThread currentThread]);
    
    NSString *cachesPath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];
    NSString *path = [cachesPath stringByAppendingPathComponent:@"usedDoors.plist"];
    
//    [[NSFileManager defaultManager]removeItemAtPath:path error:nil];
    
    if (_usedDoors.count == 0) {
        _usedDoors = [[NSMutableArray alloc]initWithContentsOfFile:path];
        if (_usedDoors.count == 0) {
            _usedDoors = [NSMutableArray array];
        }
    }
    [_usedDoors addObject:door.doorName];
//    NSLog(@"_usedDoors : %@",_usedDoors);

    int times = 0;
    NSInteger i = _usedDoors.count - 3;
//    NSLog(@"+++ i : %li",i);
    for (i = _usedDoors.count - 3; i < (NSInteger)_usedDoors.count; i++) {
//        NSLog(@"i : %li",i);
        if (i < 0) {
            continue;
        }
        if ([_usedDoors[i] isEqualToString:door.doorName]) {
            times ++;
        }
    }
//    NSLog(@"times : %i",times);
    
    LGDoor *item = _controllersInfoMArr[door.controllerIndex].doors[door.doorIndex];
//    限制频率 避免超范围
    if (item.favorite > 1000000) {
        times = 1;
    }
    
    switch (times) {
        case 2:
            item.frequency *= 3;
            break;
        case 3:
            item.frequency *= 9;
            break;
        default:
            item.frequency += 3;
            break;
    }
    
    
    if (_usedDoors.count > 10) {
        [_usedDoors removeObjectAtIndex:0];
    }
    
    [self setupUsefulFrequencyOrderDoors];
    
    [NSKeyedArchiver archiveRootObject:self.controllersInfoMArr toFile:self.controllersInfoPath];
    
    
//    NSLog(@"%@",path);
    [_usedDoors writeToFile:path atomically:YES];
    
}

- (void)log {
    NSLog(@"%@",_controllersInfoMArr);
    NSLog(@"%@",_controllers);
    NSLog(@"---------------------------");
    for (int i=0; i<_controllersInfoMArr[0].doors.count; i++) {
        NSLog(@"%p",_controllersInfoMArr[0].doors[i]);
        NSLog(@"%p",_doorsInfoMArr[i]);
        NSLog(@"%p",_doors[i]);
        NSLog(@"-----------");
        NSLog(@"ip:%p",_controllersInfoMArr[0].doors[i].ip);
        NSLog(@"ip:%p",_doorsInfoMArr[i].ip);
        NSLog(@"ip:%p",_doors[i].ip);
        NSLog(@"---------------------------");

    }
}
#pragma mark - lazy
- (NSMutableArray<LGController *> *)controllersInfoMArr {
    if (_controllersInfoMArr == nil) {
        _controllersInfoMArr = [NSKeyedUnarchiver unarchiveObjectWithFile:self.controllersInfoPath];
        
        if (_controllersInfoMArr == nil) {
            _controllersInfoMArr = [NSMutableArray array];
        }
    }
    return _controllersInfoMArr;
}
- (NSString *)controllersInfoPath {
    if (_controllersInfoPath == nil) {
        NSString *cachesPath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];
        _controllersInfoPath = [cachesPath stringByAppendingPathComponent:@"controllersInfo.data"];
    }

    return _controllersInfoPath;
}
@end

NSNotificationName const CMItemChangedNotification = @"CMItemChangedNotification";

NSNotificationName const CMDeleteAllItemNotification = @"CMDeleteAllItem";
NSNotificationName const CMAddedItemNotification = @"CMAddedItemNotification";
NSNotificationName const CMDeleteItemNotification = @"CMDeleteItemNotification";
NSNotificationName const CMEditItemNotification = @"CMEditItemNotification";
